package com.sam.controller;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.Calendar;

import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;

import ch.randelshofer.media.avi.AVIOutputStream;

import com.sam.DataStream;
import com.sam.db.Database;
import com.sam.stream.CamStream;
import com.sam.stream.FileStream;
import com.sam.stream.NetworkStream;

public class SaMController extends Thread
{

	CamStream cStream = null;
	FileStream fStream = null;
	NetworkStream nStream = null;

	ThreatController tc;
	Database database = null;
	boolean valueSet = false;
	String message = null;
	DataStream data = null;
	Mat firstframe;
	Mat midframe;
	boolean write = false;

	synchronized String getMessage()
	{
		if (!valueSet)
			try
			{
				wait();
			}
			catch (InterruptedException e)
			{
				System.out.println("InterruptedException caught");
			}
		System.out.println("Got: " + message);
		valueSet = false;
		notify();
		return message;

	}

	synchronized void putMessage(String message)
	{
		if (valueSet)
			try
			{
				wait();
			}
			catch (InterruptedException e)
			{
				System.out.println("InterruptedException caught");
			}
		this.message = message;
		valueSet = true;
		System.out.println("Put: " + message);
		notify();
	}

	public SaMController(FileStream fStream, CamStream cStream)
	{
		this.cStream = cStream;
		this.fStream = fStream;
		database = new Database();

		this.nStream = new NetworkStream(new NetworkStream.OnMessageReceived()
		{

			@Override
			public void messageReceived(DataStream dat)
			{
				System.out.println(dat.getmessage());
				data = dat;
				putMessage(dat.getmessage());
				System.out.println("message= " + message);

			}
		});
		start();
		nStream.start();
		tc = new ThreatController(2);
		data = new DataStream();

	}

	@Override
	public void run()
	{
		super.run();
		putMessage("none");
		System.out.println("main threat is running");
		boolean illegal = false;
		Mat frame = new Mat();
		boolean found = false;
		String videoname = null;
		String vid = null;
		String message = "none";
		boolean newMessage = false;
		cStream.open();
		int i = 0;
		boolean live = false;
		for (int k = 0; k < 5; k++)
			cStream.read();

		frame = (Mat) cStream.read();
		firstframe = frame.clone();
		while (true)
		{
			midframe = frame.clone();
			frame = (Mat) cStream.read();
			Highgui.imwrite("mei.jpg", frame);

			fStream.first30sec();
			if (valueSet)
			{
				message = getMessage();
				if (data.getData() != null)
					vid = data.getData()[0];
				newMessage = true;
				// live = false;
			}

			if (message.equals("login"))
			{
				String[] sessionId = new String[1];
				putMessage("none");
				String[] a = data.getData();
				if (database.auth(a))
				{
					database.setSessionId(a[0]);

					sessionId[0] = database.getSessionId(a[0]);
				}
				else
				{
					sessionId = new String[1];
					sessionId[0] = "none";
				}
				nStream.sendMessage(new DataStream("sessionId", null, sessionId));
				newMessage = false;

			}
			else if (message.equals("live"))
			{
				nStream.sendMessage(new DataStream("frames", fStream
						.getBtyeFrame(), null));
				message = "live";
			}
			else if (message.equals("stoplive"))
			{
				putMessage("none");
				live = false;

			}
			else if (message.equals("video"))
			{
				String[] a = database.getThreats();
				putMessage("none");
				nStream.sendMessage(new DataStream("videoRes", null, a));
				newMessage = false;
			}

			if (message.equals("real"))
			{
				putMessage("none");
				database.setStatus(vid, "real");
				newMessage = false;
			}
			else if (message.equals("false"))
			{
				putMessage("none");
				database.setStatus(vid, "falsealarm");
				newMessage = false;
			}
			if (message.equals("attend"))
			{
				putMessage("none");
				// try
				// {
				/*
				 * if (fStream.getSize() < 600) { String inVid = videoname;
				 * inVid=inVid+"incom"; fStream.write(inVid, new File(
				 * "demo.avi"), AVIOutputStream.VideoFormat.RAW, 24,
				 * 1f,"incom"); String[] data = new String[1]; data[0] = inVid;
				 */
				nStream.sendMessage(new DataStream("play", null, null));
				// }
				/*
				 * else { String[] data = new String[1]; data[0] = videoname;
				 * nStream.sendMessage(new DataStream("play",
				 * fStream.getBtyeFrame(),null)); }
				 */

				DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
				Calendar cal = Calendar.getInstance();
				String[] a =
				{ videoname, dateFormat2.format(cal.getTime()), "attended" };
				database.insertAlert(a);

				// }
				// catch (IOException e)
				// {
				// TODO Auto-generated catch block
				// e.printStackTrace();
				// }
				newMessage = false;
			}
			else if (message.equals("rejected"))
			{
				putMessage("none");
				DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
				Calendar cal = Calendar.getInstance();
				String[] a =
				{ videoname, dateFormat2.format(cal.getTime()), "rejected" };
				database.insertAlert(a);
				newMessage = false;
			}
			newMessage = false;

			if (illegal == false && live == false)
			{

				if (tc.getmethod().equals("FaceDetection"))
					found = tc.FaceDetection(frame);
				
				else if (tc.getmethod().equals("MotionDetection"))
				{
					

					if (i >= 5)
					{
						found = tc.MotionDetection(frame, firstframe, midframe);
						i = 0;

					}
					i++;
				}

				if (found)
				{
					illegal = true;
					System.out.println("networkStream avaiable");
					DateFormat dateFormat = new SimpleDateFormat(
							"HH_mm_ss_yyyy_MM_dd");
					Calendar cal = Calendar.getInstance();
					videoname = dateFormat.format(cal.getTime());

					DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
					Calendar cal2 = Calendar.getInstance();
					String[] a =
					{ videoname, dateFormat2.format(cal2.getTime()), "" };
					database.insertAlert(a);
					if (nStream.getOIS() != null)
					{
						nStream.sendMessage(new DataStream("threat", null, null));

					}
					else
					{
						database.setAlertStatus(videoname, "unreachable");
					}

					found = false;
				}

			}
			if (illegal)
			{

//				System.out.println("illegal");


				boolean write = fStream.writeFrameBuffer();
				if (write)
				{
					System.out.println("writing video");
					String[] arg = new String[3];
					DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
					Calendar cal = Calendar.getInstance();
					arg[0] = videoname;
					arg[1] = dateFormat2.format(cal.getTime());

					try
					{
						fStream.write(videoname, new File("demo.avi"),
								AVIOutputStream.VideoFormat.RAW, 24, 1f, "full");
						database.insertMovie(arg);
					}
					catch (IOException e)
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					fStream.resetSize(0);
					illegal = false;
					videoname = null;

				}

			}

		}

	}
}
